#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "soc/soc_caps.h"
#include "esp_log.h"
#include "driver/i2c.h"

// 全局常量, 字符串, 用于日志打印的标签
const static char *TAG = "I2C";

#define I2C_MASTER_NUM                  0

#define AHT10_IIC_ADDR	                0x38			//AHT10 IIC地址
#define AHT10_CMD_CALIBRATION    	    0xE1 	        //校准命令(上电后只需要发送一次)
#define AHT10_CMD_NORMAL     		    0xA8 	        //正常工作命令
#define AHT10_CMD_GET_DATA 			    0xAC 	        //读取数据命令


// 读取AHT10寄存器数据
static esp_err_t aht10_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
{
    return i2c_master_write_read_device(I2C_MASTER_NUM, AHT10_IIC_ADDR, &reg_addr, 1, data, len, 1000 / portTICK_PERIOD_MS);
}

// 写入数据到AHT10寄存器
static esp_err_t aht10_register_write_byte(uint8_t reg_addr, uint8_t *data, size_t len)
{
    int ret; 
    uint8_t write_buf[64];
    write_buf[0] = reg_addr;
    memcpy(write_buf+1, data, len);
    ret = i2c_master_write_to_device(I2C_MASTER_NUM, AHT10_IIC_ADDR, write_buf, len+1, 1000 / portTICK_PERIOD_MS);
    return ret;
}

// I2C初始化
esp_err_t i2c_init(void)
{
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = 4,
        .scl_io_num = 5,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = 400000,
    };

    // 设置I2C总线参数
    i2c_param_config(I2C_MASTER_NUM, &conf);
    // 安装I2C总线驱动
    return i2c_driver_install(I2C_MASTER_NUM, conf.mode, 0, 0, 0); 
}

void app_main(void)
{
    uint8_t data[6]={0,0,0,0,0,0};
    float temperature, humidity;

    // I2C初始化
    ESP_ERROR_CHECK(i2c_init());

    // 对AHT10写入开机命令, 如果I2C通信失败，会报错重启
    ESP_ERROR_CHECK(aht10_register_write_byte(AHT10_CMD_NORMAL, data, 2));
    vTaskDelay(pdMS_TO_TICKS(300));

    //  对AHT10写入校准命令, 如果I2C通信失败，会报错重启
    ESP_ERROR_CHECK(aht10_register_write_byte(AHT10_CMD_CALIBRATION, data, 2));
    vTaskDelay(pdMS_TO_TICKS(300));

    while (1) {
        // 对AHT10写入读取数据命令
        aht10_register_write_byte(AHT10_CMD_GET_DATA, data, 2);

        // 延时3000ms
        vTaskDelay(pdMS_TO_TICKS(3000));

        // 对AHT10读取原始数据
        aht10_register_read(AHT10_CMD_GET_DATA, data, 6);

        // 将原始数据转换成温湿度
        temperature = ((data[3] & 0x0F) << 16 | data[4] << 8 | data[5]) * 200.0 / (1 << 20) - 50;
        humidity = ((data[1]) << 12 | data[2] << 4 | (data[3] & 0xF0)) * 100.0 / (1 << 20);
        ESP_LOGI(TAG, "温度 = %f ℃ , 湿度 = %f %%", temperature, humidity);
    }

    // 删除I2C总线驱动
    i2c_driver_delete(I2C_MASTER_NUM);
}
